home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / manage / snmp / cmu-snmp1.0 / snmplib / mib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-20  |  17.3 KB  |  805 lines

  1. /***********************************************************
  2.     Copyright 1988, 1989 by Carnegie Mellon University
  3.  
  4.                       All Rights Reserved
  5.  
  6. Permission to use, copy, modify, and distribute this software and its 
  7. documentation for any purpose and without fee is hereby granted, 
  8. provided that the above copyright notice appear in all copies and that
  9. both that copyright notice and this permission notice appear in 
  10. supporting documentation, and that the name of CMU not be
  11. used in advertising or publicity pertaining to distribution of the
  12. software without specific, written prior permission.  
  13.  
  14. CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  15. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  16. CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  17. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  18. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  19. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  20. SOFTWARE.
  21. ******************************************************************/
  22. #include <stdio.h>
  23. #include <ctype.h>
  24. #include <sys/types.h>
  25. #include <netinet/in.h>
  26. #include <sys/time.h>
  27. #include "asn1.h"
  28. #include "snmp_impl.h"
  29. #include "snmp_api.h"
  30. #include "parse.h"
  31.  
  32. static void sprint_by_type();
  33.  
  34. static char *
  35. uptimeString(timeticks, buf)
  36.     register long timeticks;
  37.     char *buf;
  38. {
  39.     int    seconds, minutes, hours, days;
  40.  
  41.     timeticks /= 100;
  42.     days = timeticks / (60 * 60 * 24);
  43.     timeticks %= (60 * 60 * 24);
  44.  
  45.     hours = timeticks / (60 * 60);
  46.     timeticks %= (60 * 60);
  47.  
  48.     minutes = timeticks / 60;
  49.     seconds = timeticks % 60;
  50.  
  51.     if (days == 0){
  52.     sprintf(buf, "%d:%02d:%02d", hours, minutes, seconds);
  53.     } else if (days == 1) {
  54.     sprintf(buf, "%d day, %d:%02d:%02d", days, hours, minutes, seconds);
  55.     } else {
  56.     sprintf(buf, "%d days, %d:%02d:%02d", days, hours, minutes, seconds);
  57.     }
  58.     return buf;
  59. }
  60.  
  61. static sprint_hexstring(buf, cp, len)
  62.     char *buf;
  63.     u_char  *cp;
  64.     int        len;
  65. {
  66.  
  67.     for(; len >= 16; len -= 16){
  68.     sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  69.     buf += strlen(buf);
  70.     cp += 8;
  71.     sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X\n", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  72.     buf += strlen(buf);
  73.     cp += 8;
  74.     }
  75.     for(; len > 0; len--){
  76.     sprintf(buf, "%02X ", *cp++);
  77.     buf += strlen(buf);
  78.     }
  79.     *buf = '\0';
  80. }
  81.  
  82. static sprint_asciistring(buf, cp, len)
  83.     char *buf;
  84.     u_char  *cp;
  85.     int        len;
  86. {
  87.     int    x;
  88.  
  89.     for(x = 0; x < len; x++){
  90.     if (isprint(*cp)){
  91.         *buf++ = *cp++;
  92.     } else {
  93.         *buf++ = '.';
  94.         cp++;
  95.     }
  96.     if ((x % 48) == 47)
  97.         *buf++ = '\n';
  98.     }
  99.     *buf = '\0';
  100. }
  101.  
  102. #ifdef UNUSED
  103. int
  104. read_rawobjid(input, output, out_len)
  105.     char *input;
  106.     oid *output;
  107.     int    *out_len;
  108. {
  109.     char    buf[12], *cp;
  110.     oid        *op = output;
  111.     int        subid;
  112.  
  113.     while(*input != '\0'){
  114.     if (!isdigit(*input))
  115.         break;
  116.     cp = buf;
  117.     while(isdigit(*input))
  118.         *cp++ = *input++;
  119.     *cp = '\0';
  120.     subid = atoi(buf);
  121.     if(subid > MAX_SUBID){
  122.         fprintf(stderr, "sub-identifier too large: %s\n", buf);
  123.         return 0;
  124.     }
  125.     if((*out_len)-- <= 0){
  126.         fprintf(stderr, "object identifier too long\n");
  127.         return 0;
  128.     }
  129.     *op++ = subid;
  130.     if(*input++ != '.')
  131.         break;
  132.     }
  133.     *out_len = op - output;
  134.     if (*out_len == 0)
  135.     return 0;
  136.     return 1;
  137. }
  138.  
  139. #endif /* UNUSED */
  140.  
  141. static void
  142. sprint_octet_string(buf, var)
  143.     char *buf;
  144.     struct variable_list *var;
  145. {
  146.     int hex, x;
  147.     u_char *cp;
  148.  
  149.     if (var->type != ASN_OCTET_STR){
  150.     sprintf(buf, "Wrong Type (should be OCTET STRING): ");
  151.     buf += strlen(buf);
  152.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  153.     return;
  154.     }
  155.     hex = 0;
  156.     for(cp = var->val.string, x = 0; x < var->val_len; x++, cp++){
  157.     if (!(isprint(*cp) || isspace(*cp)))
  158.         hex = 1;
  159.     }
  160.     if (var->val_len <= 4)
  161.     hex = 1;    /* not likely to be ascii */
  162.     if (hex){
  163.     sprintf(buf, "OCTET STRING-   (hex):\t");
  164.     buf += strlen(buf);
  165.     sprint_hexstring(buf, var->val.string, var->val_len);
  166.     } else {
  167.     sprintf(buf, "OCTET STRING- (ascii):\t");
  168.     buf += strlen(buf);
  169.     sprint_asciistring(buf, var->val.string, var->val_len);
  170.     }
  171. }
  172.  
  173. static void
  174. sprint_opaque(buf, var)
  175.     char *buf;
  176.     struct variable_list *var;
  177. {
  178.  
  179.     if (var->type != OPAQUE){
  180.     sprintf(buf, "Wrong Type (should be Opaque): ");
  181.     buf += strlen(buf);
  182.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  183.     return;
  184.     }
  185.     sprintf(buf, "OPAQUE -   (hex):\t");
  186.     buf += strlen(buf);
  187.     sprint_hexstring(buf, var->val.string, var->val_len);
  188. }
  189.  
  190. static void
  191. sprint_object_identifier(buf, var)
  192.     char *buf;
  193.     struct variable_list *var;
  194. {
  195.     if (var->type != ASN_OBJECT_ID){
  196.     sprintf(buf, "Wrong Type (should be OBJECT IDENTIFIER): ");
  197.     buf += strlen(buf);
  198.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  199.     return;
  200.     }
  201.     sprintf(buf, "OBJECT IDENTIFIER:\t");
  202.     buf += strlen(buf);
  203.     sprint_objid(buf, (oid *)(var->val.objid), var->val_len / sizeof(oid));
  204. }
  205.  
  206. static void
  207. sprint_timeticks(buf, var)
  208.     char *buf;
  209.     struct variable_list *var;
  210. {
  211.     char timebuf[32];
  212.  
  213.     if (var->type != TIMETICKS){
  214.     sprintf(buf, "Wrong Type (should be Timeticks): ");
  215.     buf += strlen(buf);
  216.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  217.     return;
  218.     }
  219.     sprintf(buf, "Timeticks: (%d) %s", *(var->val.integer), uptimeString(*(var->val.integer), timebuf));
  220. }
  221.  
  222. static void
  223. sprint_integer(buf, var, enums)
  224.     char *buf;
  225.     struct variable_list *var;
  226.     struct enum_list        *enums;
  227. {
  228.     char    *enum_string = NULL;
  229.  
  230.     if (var->type != ASN_INTEGER){
  231.     sprintf(buf, "Wrong Type (should be INTEGER): ");
  232.     buf += strlen(buf);
  233.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  234.     return;
  235.     }
  236.     for (; enums; enums = enums->next)
  237.     if (enums->value == *var->val.integer){
  238.         enum_string = enums->label;
  239.         break;
  240.     }
  241.     if (enum_string == NULL)
  242.     sprintf(buf, "INTEGER: %d", *var->val.integer);
  243.     else
  244.     sprintf(buf, "INTEGER: %s(%d)", enum_string, *var->val.integer);
  245. }
  246.  
  247. static void
  248. sprint_gauge(buf, var)
  249.     char *buf;
  250.     struct variable_list *var;
  251. {
  252.     if (var->type != GAUGE){
  253.     sprintf(buf, "Wrong Type (should be Gauge): ");
  254.     buf += strlen(buf);
  255.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  256.     return;
  257.     }
  258.     sprintf(buf, "Gauge: %lu", *var->val.integer);
  259. }
  260.  
  261. static void
  262. sprint_counter(buf, var)
  263.     char *buf;
  264.     struct variable_list *var;
  265. {
  266.     if (var->type != COUNTER){
  267.     sprintf(buf, "Wrong Type (should be Counter): ");
  268.     buf += strlen(buf);
  269.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  270.     return;
  271.     }
  272.     sprintf(buf, "Counter: %lu", *var->val.integer);
  273. }
  274.  
  275. static void
  276. sprint_networkaddress(buf, var)
  277.     char *buf;
  278.     struct variable_list *var;
  279. {
  280.     int x, len;
  281.     u_char *cp;
  282.  
  283.     sprintf(buf, "Network Address:\t");
  284.     buf += strlen(buf);
  285.     cp = var->val.string;    
  286.     len = var->val_len;
  287.     for(x = 0; x < len; x++){
  288.     sprintf(buf, "%02X", *cp++);
  289.     buf += strlen(buf);
  290.     if (x < (len - 1))
  291.         *buf++ = ':';
  292.     }
  293. }
  294.  
  295. static void
  296. sprint_ipaddress(buf, var)
  297.     char *buf;
  298.     struct variable_list *var;
  299. {
  300.     u_char *ip;
  301.  
  302.     if (var->type != IPADDRESS){
  303.     sprintf(buf, "Wrong Type (should be Ipaddress): ");
  304.     buf += strlen(buf);
  305.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  306.     return;
  307.     }
  308.     ip = var->val.string;
  309.     sprintf(buf, "IpAddress:\t%d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]);
  310. }
  311.  
  312. static void
  313. sprint_unsigned_short(buf, var)
  314.     char *buf;
  315.     struct variable_list *var;
  316. {
  317.     if (var->type != ASN_INTEGER){
  318.     sprintf(buf, "Wrong Type (should be INTEGER): ");
  319.     buf += strlen(buf);
  320.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  321.     return;
  322.     }
  323.     sprintf(buf, "INTEGER (0..65535): %lu", *var->val.integer);
  324. }
  325.  
  326. static void
  327. sprint_null(buf, var)
  328.     char *buf;
  329.     struct variable_list *var;
  330. {
  331.     if (var->type != ASN_NULL){
  332.     sprintf(buf, "Wrong Type (should be NULL): ");
  333.     buf += strlen(buf);
  334.     sprint_by_type(buf, var, (struct enum_list *)NULL);
  335.     return;
  336.     }
  337.     sprintf(buf, "NULL");
  338. }
  339.  
  340. static void
  341. sprint_badtype(buf)
  342.     char *buf;
  343. {
  344.     sprintf(buf, "Variable has bad type");
  345. }
  346.  
  347. static void
  348. sprint_by_type(buf, var, enums)
  349.     char *buf;
  350.     struct variable_list *var;
  351.     struct enum_list        *enums;
  352. {
  353.     switch (var->type){
  354.     case ASN_INTEGER:
  355.         sprint_integer(buf, var, enums);
  356.         break;
  357.     case ASN_OCTET_STR:
  358.         sprint_octet_string(buf, var);
  359.         break;
  360.     case OPAQUE:
  361.         sprint_opaque(buf, var);
  362.         break;
  363.     case ASN_OBJECT_ID:
  364.         sprint_object_identifier(buf, var);
  365.         break;
  366.     case TIMETICKS:
  367.         sprint_timeticks(buf, var);
  368.         break;
  369.     case GAUGE:
  370.         sprint_gauge(buf, var);
  371.         break;
  372.     case COUNTER:
  373.         sprint_counter(buf, var);
  374.         break;
  375.     case IPADDRESS:
  376.         sprint_ipaddress(buf, var);
  377.         break;
  378.     case ASN_NULL:
  379.         sprint_null(buf, var);
  380.         break;
  381.     default:
  382.         sprint_badtype(buf);
  383.         break;
  384.     }
  385. }
  386.  
  387. struct tree *get_symbol();
  388.  
  389. oid RFC1066_MIB[] = { 1, 3, 6, 1, 2, 1 };
  390. unsigned char RFC1066_MIB_text[] = ".iso.org.dod.internet.mgmt.mib";
  391. struct tree *Mib;
  392.  
  393. init_mib()
  394. {
  395.     char *file, *getenv();
  396.  
  397.     Mib = read_mib("mib.txt");
  398.     if (!Mib){
  399.     file = getenv("MIBFILE");
  400.     if (file)
  401.         Mib = read_mib(file);
  402.     }
  403.     if (!Mib)
  404.     Mib = read_mib("/etc/mib.txt");
  405.     if (!Mib){
  406.     fprintf(stderr, "Couldn't find mib file\n");
  407.     exit(2);
  408.     }
  409.     set_functions(Mib);
  410. }
  411.  
  412. static
  413. set_functions(subtree)
  414.     struct tree *subtree;
  415. {
  416.     for(; subtree; subtree = subtree->next_peer){
  417.     switch(subtree->type){
  418.         case TYPE_OBJID:
  419.         subtree->printer = sprint_object_identifier;
  420.         break;
  421.         case TYPE_OCTETSTR:
  422.         subtree->printer = sprint_octet_string;
  423.         break;
  424.         case TYPE_INTEGER:
  425.         subtree->printer = sprint_integer;
  426.         break;
  427.         case TYPE_NETADDR:
  428.         subtree->printer = sprint_networkaddress;
  429.         break;
  430.         case TYPE_IPADDR:
  431.         subtree->printer = sprint_ipaddress;
  432.         break;
  433.         case TYPE_COUNTER:
  434.         subtree->printer = sprint_counter;
  435.         break;
  436.         case TYPE_GAUGE:
  437.         subtree->printer = sprint_gauge;
  438.         break;
  439.         case TYPE_TIMETICKS:
  440.         subtree->printer = sprint_timeticks;
  441.         break;
  442.         case TYPE_OPAQUE:
  443.         subtree->printer = sprint_opaque;
  444.         break;
  445.         case TYPE_NULL:
  446.         subtree->printer = sprint_null;
  447.         break;
  448.         case TYPE_OTHER:
  449.         default:
  450.         subtree->printer = sprint_badtype;
  451.         break;
  452.     }
  453.     set_functions(subtree->child_list);
  454.     }
  455. }
  456.  
  457. #ifdef testing
  458. int snmp_dump_packet = 0;
  459.  
  460. main(argc, argv)
  461.      int argc;
  462.      char *argv[];
  463. {
  464.     oid objid[64];
  465.     int objidlen = sizeof (objid);
  466.     int count;
  467.     struct variable variable;
  468.  
  469.     init_mib(&Mib);
  470.     if (argc < 2)
  471.     print_subtree(Mib, 0);
  472.     variable.type = ASN_INTEGER;
  473.     variable.val.integer = 3;
  474.     variable.val_len = 4;
  475.     for (argc--; argc; argc--, argv++) {
  476.     objidlen = sizeof (objid);
  477.     printf("read_objid(%s) = %d\n",
  478.            argv[1], read_objid(argv[1], objid, &objidlen));
  479.     for(count = 0; count < objidlen; count++)
  480.         printf("%d.", objid[count]);
  481.     printf("\n");
  482.     print_variable(objid, objidlen, &variable);
  483.     }
  484. }
  485.  
  486. #endif testing
  487.  
  488.  
  489. static struct tree *
  490. find_rfc1066_mib(root)
  491.     struct tree *root;
  492. {
  493.     oid *op = RFC1066_MIB;
  494.     struct tree *tp;
  495.     int len;
  496.  
  497.     for(len = sizeof(RFC1066_MIB)/sizeof(oid); len; len--, op++){
  498.     for(tp = root; tp; tp = tp->next_peer){
  499.         if (tp->subid == *op){
  500.         root = tp->child_list;
  501.         break;
  502.         }
  503.     }
  504.     if (tp == NULL)
  505.         return NULL;
  506.     }
  507.     return root;
  508. }
  509.  
  510. int read_objid(input, output, out_len)
  511.     char *input;
  512.     oid *output;
  513.     int    *out_len;   /* number of subid's in "output" */
  514. {
  515.     struct tree *root = Mib;
  516.     oid *op = output;
  517.     int i;
  518.  
  519.     if (*input == '.')
  520.     input++;
  521.     else {
  522.     root = find_rfc1066_mib(root);
  523.     for (i = 0; i < sizeof (RFC1066_MIB)/sizeof(oid); i++) {
  524.         if ((*out_len)-- > 0)
  525.         *output++ = RFC1066_MIB[i];
  526.         else {
  527.         fprintf(stderr, "object identifier too long\n");
  528.         return (0);
  529.         }
  530.     }
  531.     }
  532.  
  533.     if (root == NULL){
  534.     fprintf(stderr, "Mib not initialized.  Exiting.\n");
  535.     exit(1);
  536.     }
  537.     if ((*out_len =
  538.      parse_subtree(root, input, output, out_len)) == 0)
  539.     return (0);
  540.     *out_len += output - op;
  541.  
  542.     return (1);
  543. }
  544.  
  545. static
  546. parse_subtree(subtree, input, output, out_len)
  547.     struct tree *subtree;
  548.     char *input;
  549.     oid    *output;
  550.     int    *out_len;   /* number of subid's */
  551. {
  552.     char buf[128], *to = buf;
  553.     int subid = 0;
  554.     struct tree *tp;
  555.  
  556.     /*
  557.      * No empty strings.  Can happen if there is a trailing '.' or two '.'s
  558.      * in a row, i.e. "..".
  559.      */
  560.     if ((*input == '\0') ||
  561.     (*input == '.'))
  562.     return (0);
  563.  
  564.     if (isdigit(*input)) {
  565.     /*
  566.      * Read the number, then try to find it in the subtree.
  567.      */
  568.     while (isdigit(*input)) {
  569.         subid *= 10;
  570.         subid += *input++ - '0';
  571.     }
  572.     for (tp = subtree; tp; tp = tp->next_peer) {
  573.         if (tp->subid == subid)
  574.         goto found;
  575.     }
  576.     tp = NULL;
  577.     }
  578.     else {
  579.     /*
  580.      * Read the name into a buffer.
  581.      */
  582.     while ((*input != '\0') &&
  583.            (*input != '.')) {
  584.         *to++ = *input++;
  585.     }
  586.     *to = '\0';
  587.  
  588.     /*
  589.      * Find the name in the subtree;
  590.      */
  591.     for (tp = subtree; tp; tp = tp->next_peer) {
  592.         if (lc_cmp(tp->label, buf) == 0) {
  593.         subid = tp->subid;
  594.         goto found;
  595.         }
  596.     }
  597.  
  598.     /*
  599.      * If we didn't find the entry, punt...
  600.      */
  601.     if (tp == NULL) {
  602.         fprintf(stderr, "sub-identifier not found: %s\n", buf);
  603.         return (0);
  604.     }
  605.     }
  606.  
  607. found:
  608.     if(subid > MAX_SUBID){
  609.     fprintf(stderr, "sub-identifier too large: %s\n", buf);
  610.     return (0);
  611.     }
  612.  
  613.     if ((*out_len)-- <= 0){
  614.     fprintf(stderr, "object identifier too long\n");
  615.     return (0);
  616.     }
  617.     *output++ = subid;
  618.  
  619.     if (*input != '.')
  620.     return (1);
  621.     if ((*out_len =
  622.      parse_subtree(tp->child_list, ++input, output, out_len)) == 0)
  623.     return (0);
  624.     return (++*out_len);
  625. }
  626.  
  627. print_objid(objid, objidlen)
  628.     oid        *objid;
  629.     int        objidlen;    /* number of subidentifiers */
  630. {
  631.     char    buf[256];
  632.     struct tree    *subtree = Mib;
  633.  
  634.     *buf = '.';    /* this is a fully qualified name */
  635.     get_symbol(objid, objidlen, subtree, buf + 1);
  636.     printf("%s\n", buf);
  637.         
  638. }
  639.  
  640. sprint_objid(buf, objid, objidlen)
  641.     char *buf;
  642.     oid        *objid;
  643.     int        objidlen;    /* number of subidentifiers */
  644. {
  645.     struct tree    *subtree = Mib;
  646.  
  647.     *buf = '.';    /* this is a fully qualified name */
  648.     get_symbol(objid, objidlen, subtree, buf + 1);
  649. }
  650.  
  651.  
  652. print_variable(objid, objidlen, variable)
  653.     oid     *objid;
  654.     int        objidlen;
  655.     struct  variable_list *variable;
  656. {
  657.     char    buf[512], *cp;
  658.     struct tree    *subtree = Mib;
  659.  
  660.     *buf = '.';    /* this is a fully qualified name */
  661.     subtree = get_symbol(objid, objidlen, subtree, buf + 1);
  662.     cp = buf;
  663.     if ((strlen(buf) >= strlen((char *)RFC1066_MIB_text)) && !bcmp(buf, (char *)RFC1066_MIB_text,
  664.     strlen((char *)RFC1066_MIB_text))){
  665.         cp += sizeof(RFC1066_MIB_text);
  666.     }
  667.     printf("Name: %s\n", cp);
  668.     *buf = '\0';
  669.     if (subtree->printer)
  670.     (*subtree->printer)(buf, variable, subtree->enums);
  671.     else {
  672.     sprint_by_type(buf, variable, subtree->enums);
  673.     }
  674.     printf("%s\n", buf);
  675. }
  676.  
  677. sprint_variable(buf, objid, objidlen, variable)
  678.     char *buf;
  679.     oid     *objid;
  680.     int        objidlen;
  681.     struct  variable_list *variable;
  682. {
  683.     char    tempbuf[512], *cp;
  684.     struct tree    *subtree = Mib;
  685.  
  686.     *tempbuf = '.';    /* this is a fully qualified name */
  687.     subtree = get_symbol(objid, objidlen, subtree, tempbuf + 1);
  688.     cp = tempbuf;
  689.     if ((strlen(buf) >= strlen((char *)RFC1066_MIB_text)) && !bcmp(buf, (char *)RFC1066_MIB_text,
  690.     strlen((char *)RFC1066_MIB_text))){
  691.         cp += sizeof(RFC1066_MIB_text);
  692.     }
  693.     sprintf(buf, "Name: %s\n", cp);
  694.     buf += strlen(buf);
  695.     if (subtree->printer)
  696.     (*subtree->printer)(buf, variable, subtree->enums);
  697.     else {
  698.     sprint_by_type(buf, variable, subtree->enums);
  699.     }
  700.     strcat(buf, "\n");
  701. }
  702.  
  703. sprint_value(buf, objid, objidlen, variable)
  704.     char *buf;
  705.     oid     *objid;
  706.     int        objidlen;
  707.     struct  variable_list *variable;
  708. {
  709.     char    tempbuf[512];
  710.     struct tree    *subtree = Mib;
  711.  
  712.     subtree = get_symbol(objid, objidlen, subtree, tempbuf);
  713.     if (subtree->printer)
  714.     (*subtree->printer)(buf, variable, subtree->enums);
  715.     else {
  716.     sprint_by_type(buf, variable, subtree->enums);
  717.     }
  718. }
  719.  
  720. print_value(objid, objidlen, variable)
  721.     oid     *objid;
  722.     int        objidlen;
  723.     struct  variable_list *variable;
  724. {
  725.     char    tempbuf[512];
  726.     struct tree    *subtree = Mib;
  727.  
  728.     subtree = get_symbol(objid, objidlen, subtree, tempbuf);
  729.     if (subtree->printer)
  730.     (*subtree->printer)(tempbuf, variable, subtree->enums);
  731.     else {
  732.     sprint_by_type(tempbuf, variable, subtree->enums);
  733.     }
  734.     printf("%s\n", tempbuf);
  735. }
  736.  
  737. struct tree *
  738. get_symbol(objid, objidlen, subtree, buf)
  739.     oid        *objid;
  740.     int        objidlen;
  741.     struct tree    *subtree;
  742.     char    *buf;
  743. {
  744.     struct tree    *return_tree = NULL;
  745.  
  746.     for(; subtree; subtree = subtree->next_peer){
  747.     if (*objid == subtree->subid){
  748.         strcpy(buf, subtree->label);
  749.         goto found;
  750.     }
  751.     }
  752.  
  753.     /* subtree not found */
  754.     while(objidlen--){    /* output rest of name, uninterpreted */
  755.     sprintf(buf, "%d.", *objid++);
  756.     while(*buf)
  757.         buf++;
  758.     }
  759.     *(buf - 1) = '\0'; /* remove trailing dot */
  760.     return NULL;
  761.  
  762. found:
  763.     if (objidlen > 1){
  764.     while(*buf)
  765.         buf++;
  766.     *buf++ = '.';
  767.     *buf = '\0';
  768.     return_tree = get_symbol(objid + 1, objidlen - 1, subtree->child_list, buf);
  769.     } 
  770.     if (return_tree != NULL)
  771.     return return_tree;
  772.     else
  773.     return subtree;
  774. }
  775.  
  776.  
  777. static int
  778. lc_cmp(s1, s2)
  779.     char *s1, *s2;
  780. {
  781.     char c1, c2;
  782.  
  783.     while(*s1 && *s2){
  784.     if (isupper(*s1))
  785.         c1 = tolower(*s1);
  786.     else
  787.         c1 = *s1;
  788.     if (isupper(*s2))
  789.         c2 = tolower(*s2);
  790.     else
  791.         c2 = *s2;
  792.     if (c1 != c2)
  793.         return ((c1 - c2) > 0 ? 1 : -1);
  794.     s1++;
  795.     s2++;
  796.     }
  797.  
  798.     if (*s1)
  799.     return -1;
  800.     if (*s2)
  801.     return 1;
  802.     return 0;
  803. }
  804.  
  805.